EN = 0b10000000
RW = 0b01000000
RS = 0b00100000
EN|RS = 0b10100000

reset:
  ldr OPB, #0b00111000       ; set 8-bit mode, 2-line display, 5x8 font
  call lcd_instruction
  
  ldr OPB, #0b00001110       ; set display on, curson off, blink off 
  call lcd_instruction

  ldr OPB, #0b00000110       ; increment and shift cursor
  call lcd_instruction

  ldr OPB, #0b00000001       ; clear display
  call lcd_instruction

init_score_display:
  ldr D, top_line_text
  call print_text_pointed_by_d

main_loop:
  call select_current_combination
  call check_player_input
  jump main_loop

; player has to input right combination
; pressing the wrong button is an error and ends the game
check_player_input:
  mov IPA, A                ; input is in A
  shr A
  shr A
  shr A 
  shr A                      ; shift AAAAXXXX into 0000AAAA

  mov A, C                    ; save A
  
  inv B                     ; invert B
  
  nor B                     ; check for errors
  
  jmnz error_detected

  mov C, A                     ; return A

  inv B                      ; inv B back

  cmp B                     ; check if A = B (input combination == desired combination)

  jmz correct_input_detected

  jump check_player_input


error_detected:
  ldr OPB, #0x80                ; move cursor to first line, 0th position
  call lcd_instruction

  ldr D, game_over_text
  call print_text_pointed_by_d

  hlt

correct_input_detected:
  call increment_score_in_memory
  call update_score

wait_for_button_release:
  mov IPA, A
  shr A
  shr A
  shr A
  shr A

  cmp #0x0f

  jmnz wait_for_button_release

  ret                ; return to main loop




select_current_combination:
  mov IPA, A                    ; random number is in A
  and #0x0f                     ; and with 00001111 -> lower half is saved
  mov A, B                      ; current combination is in B

update_current_combination_on_lcd:
  ldr OPB, #0x80                ; move cursor to first line, 0th position
  call lcd_instruction

  ldr C, #0x08

update_current_combination_on_lcd_loop:

  mov B, A

  and C                         ; and bit with the current position

  jmz print_full_space

print_blank_space:
  ldr OPB, #0b11011011               ; "_"
  call lcd_character
  jump print_combination_character_end

print_full_space:
  ldr OPB, #0xFF                ; block
  call lcd_character

print_combination_character_end:

  mov C, A                      ; move C to A
  shr A                         ; shift bit right
  cmp #0x00                     ; compare to zero

  rtz                           ; return if zero

  mov A, C

  jump update_current_combination_on_lcd_loop








update_score:
  ldr OPB, #0x8D                ; move cursor to first line, Dth (13th) position
  call lcd_instruction

  ldr D, score_text            ; address of score_text is now in D
  call print_text_pointed_by_d

  ret

increment_score_in_memory:
  ldr D, end_score           ; address right after the last digit of score is in D
  dec D                      ; address of the last digit is in D
  dec D

  ldm $D, A                  ; value of ones place is in A
  cmp #0x39                  ; compare with 0x39 - "9"

  jmz digit_overflow         ; ones overflow to tens

increment_current_digit:
  inc A                      
  stm A, $D                  ; otherwise increment A and store the same character to memory
  ret                        ; then return

digit_overflow:
  ldr A, #0x30               ; load "0" to A
  stm A, $D                  ; zero is now in ones place in memory

  dec D                      ; D now pointing to higher value

  ldm $D, A                  ; value of higher place is in A
  cmp #0x39                  ; compare to 9

  jmz digit_overflow

  cmp #0x20                  ; compare to " " - end loop

  rtz                        ; return if pointed character is space

  jump increment_current_digit

print_text_pointed_by_d:
  ldm $D, A                  ; char pointed to by D is now in A
  cmp #0x00                  ; compare with zero

  rtz                       ; return if zero

  mov A, OPB                ; letter is in reg. A, move to OPB
  call lcd_character
  
  inc D

  jump print_text_pointed_by_d

lcd_instruction:
  ldr OPA, #0               ; clear RS/RW/EN bits
  ldr OPA, EN               ; toggle ENable pin
  ldr OPA, #0               ; clear RS/RW/EN bits
  ret

lcd_character:
  ldr OPA, RS               ; set RS bit
  ldr OPA, EN|RS            ; toggle ENable pin
  ldr OPA, RS               ; clear ENable bit
  ret

                    ;"0123456789abcdef"
top_line_text: ascii "      Score: "
score_text: asciiz "000"        ; 0 - 0x30; 9 - 0x39
end_score:
game_over_text: asciiz "Game over!"